package org.extdev.connection.serialport;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.extdev.connection.ConnectionException;
import org.extdev.connection.MutableConnection;


/**
 * @author KhaosKat
 * @author LAP
 * KhaosKat - Create ComPortConnection class wrap rxtx Library
 * LAP - Extraction serial port parameters to other class
 */
public class SerialPortConnection implements MutableConnection {
    private SerialPort serialPort;
    private SerialPortPreferences serialPortPreferences;
    private CommPortIdentifier portId;
    private boolean connected = false;

    //constructors
    public SerialPortConnection() throws NoSuchPortException {
    	this(new SerialPortPreferences());
    }
    
    public SerialPortConnection(SerialPortPreferences serialPortPreferences) throws NoSuchPortException{
    	this.setSerialPortPreferences(serialPortPreferences);
    	portId = CommPortIdentifier.getPortIdentifier(getSerialPortPreferences().getPortName());
    }

    @Override
    public void connect() throws IOException, UnsupportedCommOperationException, PortInUseException, ConnectionException {
            CommPort commPort = portId.open(this.getClass().getName(), getSerialPortPreferences().getTIMEOUT());
            if (commPort instanceof SerialPort) {
                this.serialPort = (SerialPort) commPort;
            } 
            else {
            	throw new ConnectionException(getSerialPortPreferences().getPortName() + " is not serial port");
            }
            connected = true;
    }
    
    public void setSerialPortParams() throws UnsupportedCommOperationException, ConnectionException {
    	if(!connected) throw new ConnectionException(getSerialPortPreferences().getPortName() + " not connected");
        this.serialPort.setSerialPortParams(
        		getSerialPortPreferences().getSpeed(), 
        		getSerialPortPreferences().getDataBits(), 
        		getSerialPortPreferences().getStopBits(), 
        		getSerialPortPreferences().getParity());
    }

    @Override
    public void disconnect() {
        if (serialPort != null) {
            serialPort.close();
        }
        connected = false;
    }
    @Override
    public InputStream getInputStream() throws IOException {
        return serialPort.getInputStream();
    }
    @Override
    public OutputStream getOutputStream() throws IOException {
        return serialPort.getOutputStream();
    }

	/**
	 * @return the serialPortPreferences
	 */
	public SerialPortPreferences getSerialPortPreferences() {
		return serialPortPreferences;
	}

	/**
	 * @param serialPortPreferences the serialPortPreferences to set
	 */
	public void setSerialPortPreferences(SerialPortPreferences serialPortPreferences) {
		this.serialPortPreferences = serialPortPreferences;
	}

	@Override
	public boolean isConnected() {
		return connected;
	}
}
